﻿using KAs.Application.Contract.Dto;
using KAs.Application.Contract.Dto.Interface;
using KAs.Application.Contract.Svc;
using KAs.SqlSugar;
using KAs.SqlSugar.Entity;
using Microsoft.Extensions;
using SqlSugar;

namespace KAs.Application;

/// <summary>
/// 通用应用服务
/// </summary>
/// <typeparam name="TPrimaryKeyType">主键类型</typeparam>
/// <typeparam name="T">实体类</typeparam>
/// <typeparam name="TCreateDto">实体创建Dto类</typeparam>
/// <typeparam name="TUpdateDto">实体更新Dto类</typeparam>
/// <typeparam name="TDto"></typeparam>
public abstract class CommonCurdAppService<TPrimaryKeyType, T, TCreateDto, TUpdateDto, TDto> :
    ICommonCurdAppService<TPrimaryKeyType, T, TCreateDto, TUpdateDto, TDto>
    where T : Entity<TPrimaryKeyType>, new()
    where TCreateDto : IEntityDto<TPrimaryKeyType>, new()
    where TUpdateDto : IEntityDto<TPrimaryKeyType>, new()
    where TDto : IEntityDto<TPrimaryKeyType>, new()
{
    protected IRepository<T, TPrimaryKeyType> _repository;

    public CommonCurdAppService(IRepository<T, TPrimaryKeyType> repository)
    {
        _repository = repository;
    }

    public virtual async Task<TPrimaryKeyType> CreateAsync(TCreateDto createDto)
    {
        var entity = createDto.SimpleMapTo<T>();
        entity.Id = default;
        entity = await _repository.InsertReturnEntityAsync(entity);
        return entity.Id;
    }

    public virtual async Task<bool> UpdateAsync(TUpdateDto updateDto)
    {
        var entity = await _repository.GetByIdAsync(updateDto.Id);
        updateDto.SimpleMapTo(entity);
        return await _repository.UpdateAsync(entity);
    }

    public virtual async Task<bool> DeleteAsync(TPrimaryKeyType id)
    {
        return await _repository.DeleteInAsync(id);
    }

    public virtual async Task<TDto> GetAsync(TPrimaryKeyType id)
    {
        var entity = await _repository.GetByIdAsync(id);
        if (entity == null)
            return null;
        else
            return entity.SimpleMapTo<TDto>();
    }

    public abstract Task<PageReturnDto<TDto>> GetPageListAsync(PageReqDto pageReqDto);

    protected async Task<PageReturnDto<TDto>> PageAsync(int pageIndex, int pageSize,
        Expressionable<T> condition, IDictionary<string, string> orderDic)
    {
        if (pageSize <= 0 || pageIndex < 0)
        {
            return new PageReturnDto<TDto>()
            {
                PageIndex = pageIndex,
                PageSize = pageSize,
                PageCount = 0,
                TotalCount = 0,
                Data = new List<TDto>()
            };
        }
        // 添加条件
        var queryable = _repository.AsQueryable().Where(condition.ToExpression());
        // 排序
        var tProperties = typeof(T).GetProperties();
        foreach (var item in orderDic.Keys)
        {
            if (!orderDic[item].Equals("asc", StringComparison.OrdinalIgnoreCase)
                && !orderDic[item].Equals("desc", StringComparison.OrdinalIgnoreCase))
                continue;
            var orderByType = orderDic[item].Equals("asc", StringComparison.OrdinalIgnoreCase) ? "asc" : "desc";
            var orderByFieldName = _repository.GetDbColumnName(item);
            queryable = queryable.OrderBy($"{orderByFieldName} {orderByType} ");
        }
        // 分页查询
        RefAsync<int> total = 0;
        var pageList = await queryable.ToPageListAsync(pageIndex, pageSize, total);

        var result = new PageReturnDto<TDto>()
        {
            PageIndex = pageIndex,
            PageSize = pageSize,
            PageCount = Convert.ToInt32(Math.Ceiling(total * 1.0 / pageSize)),
            TotalCount = total,
            Data = pageList.Select(x => x.SimpleMapTo<TDto>()).ToList() ?? new List<TDto>()
        };
        return result;
    }

}
